package dao

import (
	"context"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"proxy_resource_test/config"
	"proxy_resource_test/utils/logging"
	"sync"
	"time"
)

var sqlClient *gorm.DB

type MySQLFactory struct {
	once sync.Once
	mdb  *gorm.DB
}

func NewMySQLFactory() *MySQLFactory {
	return &MySQLFactory{}
}

func init() {
	RegisterFactory(NewMySQLFactory())
}

func (m *MySQLFactory) Connect(ctx context.Context) error {
	var errConn error
	m.once.Do(func() {
		cfg := config.DatabaseConfig
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%t&loc=%s",
			cfg.User,
			cfg.Password,
			cfg.Host,
			cfg.Port,
			cfg.DbName,
			"utf8",
			true,
			"Local",
		)
		db, err := makeDb(dsn)
		if err != nil {
			errConn = fmt.Errorf("连接数据库失败: %w", err)
			logging.Error("连接数据库失败", "dsn", dsn, "err", err)
			m.mdb = nil
			return
		}

		// 配置连接池
		sqlDB, err := db.DB()
		if err != nil {
			errConn = fmt.Errorf("获取数据库连接失败: %w", err)
			logging.Error("连接数据库失败", "dsn", dsn, "err", err)
			m.mdb = nil
		}
		sqlDB.SetMaxIdleConns(10)
		sqlDB.SetMaxOpenConns(100)
		sqlDB.SetConnMaxLifetime(time.Hour)
		m.mdb = db
		sqlClient = db
		logging.Info("MySQL 已连接")
	})
	return errConn
}

func (m *MySQLFactory) Close() error {
	if m.mdb == nil {
		return nil
	}
	sqlDB, err := m.mdb.DB()
	if err != nil {
		return err
	}
	if err := sqlDB.Close(); err != nil {
		return fmt.Errorf("MySQL 关闭失败: %w", err)
	}
	return nil
}

func makeDb(dsn string) (*gorm.DB, error) {
	dbConfig := &gorm.Config{}
	if config.AppConfig.Env == "dev" {
		dbConfig.Logger = logger.Default.LogMode(logger.Info)
	}
	db, err := gorm.Open(mysql.Open(dsn), dbConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to connect to MySQL: %w", err)
	}
	return db, err
}

// GetSqlDB  APP链接库
func GetSqlDB() *gorm.DB {
	if sqlClient == nil {
		logging.Error("mysql 未成功初始化")
	}
	return sqlClient
}
